/*

    raee_final
    Richard Edden

    Last Modified:  July 11, 2003
    

This program is designed to deal with a "double" experiment, removing the one-bond
and n-bond correlations from 2-D experiments.
For full details of what is does, see the documentation.



*/

//  Declare some constants and variables

#define PAR1D       0   // 1 dimensional hmbc
#define PAR2D       1   // 2 dimensional hmbc

int p,q,a,a2,counter,
    pmin, qmin,
    i,
    j,
    k,
    iParmode,           // 1D, 2D or 3D spectrum
    iLeftPoint,         // Edges of region to be excised
    iRightPoint,
    iSI,                // SI
    Row,                // Row of 2D to be pulled out.
    Procno1d,           // Process number it is moved to.
    expno1d,
    expnoone,
    expnoerr,
    expnohmbc, expnostore,
    expnoslice,
    expnomodel,         // expno of regenerated fid.
    expnopeak,
    *iBuffer,
    *iBuffer2,
    *iBuffer3,
    *iclay,
    *imodel,
    *itemplate,
    *idydA,
    *idydJ,
 *idydW,
    ihmbcswitch, Doctor, iswitch,
    imodelswitch, ihalfswitch,
    iD,         //  Number of datapoints in D2
    iTD,
    iTD_2D,
    iWindow,
    slice_filsiz,
    model_filsiz;

float   fphc0,          // phase corrections
    fphc20,         // To select imaginary part at the end (= fphc0 + 90)
    fphc1,
    fOffset,            //
    fOffset_2D,
    fRightPPM,          // Edges of region to be excised ppm
    fLeftPPM,
    fsliceRightPPM,
    fsliceLeftPPM,
    fDW,
    fDW_2D,
    fTime,          // Time in fid
    fJtest,fJtestmin, fJtestmax, foneJ,   // Trial value of J, range of trials of J, one-bond J
    fSinpijt, fCospijt,fSinWt, fCosWt,
    fLB,fLB2,fGB2,
    fD20,fP16,fD2,fD3, fD7,fP11, fP4,
    fA, fAmax, fAmin, // Fitting parameter A, range of trials of A
    fAbest,fJbest,fW,fWbest,
    dy,dz,flamda,fDA,fDJ,
   Number,
     gamma,  //gamma is the step limiter
    alpha[2][2];
double fDelay,          //D2/DW
    dMin,
    dMax,
fhorse,fgoat,
    beta[3],betaold[3],fChisq, foChisq,fDChisq,
    dChisq[512][512];           //Chi squared

double *dbox;

const float Pi = 3.1415927;

char    fn1d[PATH_LENGTH],
    fname[PATH_LENGTH],
    fnpeak[PATH_LENGTH],
    fnmodel[PATH_LENGTH],
    fntitle[PATH_LENGTH],
    fnmodelfid[PATH_LENGTH],
    fnslice[PATH_LENGTH],
    fnslicefid[PATH_LENGTH],
    fnerr[PATH_LENGTH];
double dSW;

FILE    *fp1r,          //1d file (2dexpno, procno1d)
    *fx1r,
    *fq1r,          //model file (2dexpno+100)
    *fr1r,          //2d row file
    *fs1r;

char data_path[PATH_LENGTH];
char line[255];
FILE    *filein;
double dsliceRightPPM,dsliceLeftPPM,dRightPPM,dLeftPPM;

// Begin Program

GETCURDATA;
FETCHPARS("PARMODE",&iParmode);
a=16;

ihmbcswitch=iParmode+1;
GETINT("Are you using a 1D (1) or 2D (2) hmbc?",ihmbcswitch);
imodelswitch=2;
GETINT("Model from proton (1) onebond (2) or half-onebond (3)?",imodelswitch);

//  Define experiment structure

expnohmbc = expno;
expno1d = 15;
//expno1d = expnohmbc+1;
//expnopeak = expnohmbc+5;
expnopeak = 119;
//expnomodel = expnohmbc+4;
expnomodel = 120;
//expnoslice = expnohmbc+3;
expnoslice = 125;
//expnoerr = expnohmbc+2;
expnoerr = 130;
expnostore = 1000;
GETINT("Store No?",expnostore);
//Fetch the error map dataset.

(void)sprintf( fname,"%s",name);

DATASET("errormap", 1, 1, disk, user);
VIEWDATA;
WRPA(fname, expnoerr, 1, disk, user);



DATASET(fname, expnohmbc, 1, disk, user);

VIEWDATA;
//GETINT("Expno of HMBC: ", expnohmbc);

switch (imodelswitch){
case 1:
GETINT("Expno of 1-D proton spectrum: ", expno1d);
break;
case 2:
expno1d=expnohmbc+1;
GETINT("Expno of first One-Bond spectrum: ", expno1d);
break;
case 3:
expno1d=expnohmbc+1;
GETINT("Expno of first One-Bond spectrum: ", expno1d);
break;
}



(void)sprintf( fn1d,"%s/data/%s/nmr/%s/%d/pdata/%d/1r",disk,user,name,expno1d,procno);
//GETINT("Expno to model in: ", expnomodel);
    (void)sprintf( fnmodel,"%s/data/%s/nmr/%s/%d/pdata/%d/1r",disk,user,name,expnomodel,procno);
    (void)sprintf( fnmodelfid,"%s/data/%s/nmr/%s/%d/fid",disk,user,name,expnomodel);
expnopeak = expnomodel-1;
//GETINT("Expno to put HMBC slice in: ", expnoslice);
    (void)sprintf( fnslice,"%s/data/%s/nmr/%s/%d/pdata/%d/1r",disk,user,name,expnoslice,procno);
    (void)sprintf( fnslicefid,"%s/data/%s/nmr/%s/%d/fid",disk,user,name,expnoslice);
//GETINT("Expno to put error map in: ", expnoerr);
    (void)sprintf( fnerr,"%s/data/%s/nmr/%s/%d/pdata/%d/2rr",disk,user,name,expnoerr,procno);
    (void)sprintf( fnpeak,"%s/data/%s/nmr/%s/%d/pdata/%d/1r",disk,user,name,expnopeak,procno);


// Collect 1D parameters of interest

DATASET(name, expno1d, 1, disk, user);
FETCHPAR("PHC0",&fphc0);
FETCHPAR("PHC1",&fphc1);
FETCHPAR("OFFSET",&fOffset);
FETCHPARS("SI",&iSI);
FETCHPARS("SW",&dSW);
FETCHPAR("TD",&iTD);
FETCHPAR("LB",&fLB);
FETCHPAR("DW",&fDW);        //  fetches in microseconds.
fDW /= 1000000.0;           //  now in s






// Pull row from 2D file.


DATASET(name, expnohmbc, 1, disk, user);
FETCHPAR("D 2",&fD2);

FETCHPARS("WDW",&iWindow);
FETCHPARS("GB",&fGB2);
FETCHPARS("LB",&fLB2);

if (imodelswitch == 1 ) {    
    DATASET(name, expno1d, 1, disk, user);
    STOREPAR("WDW",0);
    STOREPAR("GB",fGB2);
    STOREPAR("LB",fLB2);
    }
DATASET(name, expnohmbc, 1, disk, user);
FETCHPAR("D 3",&fD3);
fD20=0.00005;
FETCHPAR("P 16",&fP16);
fP16/=1000000.0;
FETCHPAR("P 4",&fP4);
fP4/=1000000.0;
FETCHPAR("P 11",&fP11);
fP11/=1000000.0;
FETCHPAR("TD",&iTD_2D);
FETCHPAR("OFFSET", &fOffset_2D);
//Proc_err(DEF_ERR_OPT,"O1: %f\nO2: %f",fOffset,fOffset_2D);
if (fOffset_2D !=fOffset){STOPMSG("Incompatible files: fOffset_2D fOffset");}
FETCHPAR("DW",&fDW_2D);     //  fetches in microseconds.
fDW_2D /= 1000000.0;            //  now in s
fD2 = fD2+.0001+2*fP16+4*fD3+fP4;
fD2 = 0.064;
if (imodelswitch == 1)GETFLOAT("Leftshift?",fD2 );
//if (ihmbcswitch == 1){fD2 = fD2-4*fD3+fP11;}

if (fDW_2D != fDW){STOPMSG("Incompatible files: fDW_2D !=fDW");}


if (ihmbcswitch == 2 ) {
    DATASET(name, expnohmbc, 1, disk, user);
    VIEWDATA;
    (void)sprintf(text, "Check n-bond row.");
    Proc_err(2, text);
    Row= 185;
    GETINT("Which row of the HMBC would you like to extract: ", Row);
    RSR(Row,2);
    DATASET(name, expnohmbc, 2, disk, user);
    VIEWDATA;
    WRPA(name, expnoslice, 1, disk, user);
    DATASET(name, expnoslice, 1, disk, user);
    VIEWDATA;
    
//Peak Doctor to the rescue.


GETINT("Hit Return or 5 to enter Peak Doctor: ", Doctor);
if (Doctor == 5 ) {
if (imodelswitch >= 2 ) {
    DATASET(name, expno1d, 1, disk, user);
    RSR(Row,2);
    DATASET(name, expno1d, 2, disk, user);
    VIEWDATA;
    WRPA(name, expnoslice-1, 1, disk, user);
    DATASET(name, expno1d+1, 1, disk, user);
    RSR(Row,2);
    DATASET(name, expno1d+1, 2, disk, user);
    VIEWDATA;
    WRPA(name, expnoslice-2, 1, disk, user);
    DATASET(name, expnoslice, 1, disk, user);
    DATASET2(name, expnoslice-1, 1, disk, user);
    DATASET3(name, expnoslice, 1, disk, user);
    VIEWDATA;
    XCMD("dual");
    VIEWDATA;
    (void)sprintf(text, "Twiddle to lose one-bond,\nhit return and Save and return\n..and then hit OK.\nThen hit Cancel and OKon the other windows.");
    Proc_err(2, text);
    XCMD("return");
    (void)sprintf(text, "Hit OK.");
    Proc_err(2, text);
    Doctor=0;
}
else
{
DATASET(name, expnohmbc+1, 1, disk, user);
    RSR(Row,2);
    DATASET(name, expnohmbc+1, 2, disk, user);
    VIEWDATA;
    WRPA(name, expnoslice-1, 1, disk, user);
    DATASET(name, expnohmbc+2, 1, disk, user);
    RSR(Row,2);
    DATASET(name, expnohmbc+2, 2, disk, user);
    VIEWDATA;
    WRPA(name, expnoslice-2, 1, disk, user);
    DATASET(name, expnoslice, 1, disk, user);
    DATASET2(name, expnoslice-1, 1, disk, user);
    DATASET3(name, expnoslice, 1, disk, user);
    VIEWDATA;
    XCMD("dual");
    VIEWDATA;
    (void)sprintf(text, "Twiddle to lose one-bond,\nhit return and Save and return\n..and then hit OK.\nThen hit Cancel and OKon the other windows.");
    Proc_err(2, text);
    XCMD("return");
    (void)sprintf(text, "Hit OK.");
    Proc_err(2, text);
    Doctor=0;
}

    }
    }
if (ihmbcswitch == 1 ) {
    DATASET(name, expnohmbc, 1, disk, user);
    WRPA(name, expnoslice, 1, disk, user);
    DATASET(name, expnoslice, 1, disk, user);
    VIEWDATA;
}

//Removing row from One-Bond correlation.

DATASET(name, expno1d, 1, disk, user);
if (imodelswitch >= 2 ) {
    Row=106;
    DATASET(name, expno1d, 1, disk, user);
    VIEWDATA;
    (void)sprintf(text, "Check one-bond row.");
    Proc_err(2, text);
    GETINT("Which row of the One-Bond correlation would you like to extract: ", Row);
    RSR(Row,2);
    DATASET(name, expno1d, 2, disk, user);
    VIEWDATA;
    WRPA(name, expnomodel, 1, disk, user);
    DATASET(name, expno1d+1, 1, disk, user);
    RSR(Row,2);
    DATASET(name, expno1d+1, 2, disk, user);
    VIEWDATA;
    WRPA(name, expnomodel-1, 1, disk, user);
    DATASET(name, expnomodel, 1, disk, user);
    DATASET2(name, expnomodel-1, 1, disk, user);
    VIEWDATA;
    XCMD("dual");
    VIEWDATA;
    (void)sprintf(text, "Check which one-bond peak is larger\nand hit OK.");
    Proc_err(2, text);
  GETINT("Which One-Bond correlation is larger? green (1) red (2): ", iswitch);
      XCMD("return");
    if (iswitch == 2)
    {
    DATASET(name, expnomodel-1, 1, disk, user);
    WRPA(name, expnomodel, 1, disk, user);
    DATASET(name, expnomodel, 1, disk, user);   
   }

//Peak Doctor to the rescue.


GETINT("Hit Return or 5 to enter Peak Doctor: ", Doctor);
if (Doctor == 5 ) {
if (iswitch == 2)
    {
DATASET(name, expno1d, 1, disk, user);
    RSR(Row,2);
    DATASET(name, expno1d, 2, disk, user);
    VIEWDATA;
    WRPA(name, expnomodel-1, 1, disk, user); 
   }    
if (iswitch == 1)
    {
    DATASET(name, expno1d+1, 1, disk, user);
    RSR(Row,2);
    DATASET(name, expno1d+1, 2, disk, user);
    VIEWDATA;
    WRPA(name, expnomodel-1, 1, disk, user);  
   }  

    DATASET(name, expnomodel, 1, disk, user);
    DATASET2(name, expnomodel-1, 1, disk, user);
    DATASET3(name, expnomodel, 1, disk, user);
    VIEWDATA;
    XCMD("dual");
    VIEWDATA;
    (void)sprintf(text, "Twiddle to lose one-bond,\nhit return and Save and return\n..and then hit OK.\nThen hit Cancel and OKon the other windows.");
    Proc_err(2, text);
    XCMD("return");
    (void)sprintf(text, "Hit OK.");
    Proc_err(2, text);
    Doctor=0;
    }


        
    VIEWDATA;
    HT;
    IFT;
    GENFID(expnomodel);
    STOREPAR("PHC0", 0.0);
    STOREPAR("PHC1", 0.0);
    FT;
   }
if (imodelswitch == 2 ) {    
    (void)sprintf(text, "Measure one-bond coupling constant\nand hit OK.");
    Proc_err(2, text);
    foneJ=168.46;
    GETFLOAT("One-bond coupling constant (Hz)?",foneJ);
    }
if (imodelswitch == 3 ) {    
    (void)sprintf(text, "Measure one-bond coupling constant\nand hit OK.");
    Proc_err(2, text);
    foneJ=168.46;
    GETFLOAT("One-bond coupling constant (Hz)?",foneJ);
    }


if (imodelswitch == 1 ) {    
DATASET(name, expno1d, 1, disk, user);
    VIEWDATA;
    WRPA(name, expnomodel, 1, disk, user);
DATASET(name, expnomodel, 1, disk, user);
FP;
VIEWDATA;
}

DATASET(name, expnoslice, 1, disk, user);
VIEWDATA;
//Automatic limit extraction on hmbc.
    XCMD("integ");
    (void)sprintf(text, "Mark boundaries of region to be excised\nhit return, then save\nand only then hit OK.");
    Proc_err(2, text);

    sprintf( data_path, "%s/data/%s/nmr/%s/%d/pdata/%d/intrng", disk, user, name, expno, procno);
    filein = fopen(data_path,"r");

    //get two lines and ignore them
    fgets(line,255,filein);
    fgets(line,255,filein);

    //read the line with data
    fgets(line,255,filein);


    sscanf(line," %lf %lf",&dsliceLeftPPM,&dsliceRightPPM);
    fclose(filein);

    fsliceLeftPPM = (float) dsliceLeftPPM;
    fsliceRightPPM = (float) dsliceRightPPM;

//Zero all other regions in the spectrum.
iLeftPoint = (int) ((fOffset-fsliceLeftPPM)/dSW*iSI);
iRightPoint = (int) ((fOffset-fsliceRightPPM)/dSW*iSI);

if ((fr1r=fopen(fnslice,"rb")) == NULL)
{
    (void)sprintf(text,"Cannot read 1r file:\n%s ",fnslice);
    STOPMSG(text);
}

iBuffer=(int *) malloc((size_t)(iSI*sizeof(int)));
if (!iBuffer) STOPMSG("Could not allocate enough memory (iBuffer)");


iBuffer2=(int *) malloc((size_t)(iSI*sizeof(int)));
if (!iBuffer2) STOPMSG("Could not allocate enough memory (iBuffer2)");  

k = fread(iBuffer,sizeof(int),iSI,fr1r);
fclose(fr1r);
if (iSI != k)   { STOPMSG("Read Error56:  SI != Number of Points Read"); }
for (k=0; k < (iLeftPoint); k++) { iBuffer[k]= 0; }
for (k=iRightPoint-1; k < (iSI); k++) { iBuffer[k]= 0; }

fr1r=fopen(fnslice,"wb");
fwrite(iBuffer,sizeof(int),iSI,fr1r);
fclose(fr1r);
STOREPAR("SI",iSI);
HT;
IFT;
GENFID(expnoslice);   //latest

if (imodelswitch == 2 ) {    
//Then read fid into Buffer and multiply it by the sin coupling function.

if ((fr1r=fopen(fnslicefid,"rb")) == NULL)
	{
    		(void)sprintf(text,"Cannot read fid:\n%s ",fnslicefid);
    		STOPMSG(text);
	}
	k = fread(iBuffer,sizeof(int),iSI,fr1r);
	fclose(fr1r);

	for (i=0; i < k-1; i = i+2) {

	fSinpijt = sin(i * fDW * foneJ * Pi);
	iBuffer[i] *= fSinpijt;
	iBuffer[i+1] *= fSinpijt;

	}

	fr1r=fopen(fnslicefid,"wb");
	fwrite(iBuffer,sizeof(int),iSI,fr1r);
	fclose(fr1r);
	
	STOREPARS("TD", iSI);
	FT;
}
if (imodelswitch == 1 ) {    

    STOREPAR("PHC0", 0.0);
    STOREPAR("PHC1", 0.0);
    FP;
    HT;
    IFT;
    GENFID(expnoslice);
    FT;
    VIEWDATA;
    STOREPAR("PHC0", 0.0);
    STOREPAR("PHC1", 0.0);
    

}
/*  Define region to be excised */

DATASET(name, expnomodel, 1, disk, user);
VIEWDATA;
    XCMD("integ");
    (void)sprintf(text, "Mark boundaries of region to be excised\nhit return, then save\nand only then hit OK.");
    Proc_err(2, text);

    sprintf( data_path, "%s/data/%s/nmr/%s/%d/pdata/%d/intrng", disk, user, name, expno, procno);
    filein = fopen(data_path,"r");

    //get two lines and ignore them
    fgets(line,255,filein);
    fgets(line,255,filein);

    //read the line with data
    fgets(line,255,filein);


    sscanf(line," %lf %lf",&dLeftPPM,&dRightPPM);
    fclose(filein);


fLeftPPM = (float) dLeftPPM;
fRightPPM = (float) dRightPPM;
iLeftPoint = (int) ((fOffset-fLeftPPM)/dSW*iSI);
iRightPoint = (int) ((fOffset-fRightPPM)/dSW*iSI);


// Try to open the file

if ((fp1r=fopen(fnmodel,"rb")) == NULL)
{
    (void)sprintf(text,"Cannot read 1r file:\n%s ",fnmodel);
    STOPMSG(text);
}


i = fread(iBuffer,sizeof(int),iSI,fp1r);
fclose(fp1r);
if (iSI != i)   { STOPMSG("Read Error1:  SI != Number of Points Read"); }


/*  Excise region of interest   */

for (i=0; i < (iLeftPoint); i++) { iBuffer[i]= 0; }
for (i=iRightPoint-1; i < (iSI); i++) { iBuffer[i]= 0; }

fp1r=fopen(fnmodel,"wb");
fwrite(iBuffer,sizeof(int),iSI,fp1r);
fclose(fp1r);

VIEWDATA;

HT;
IFT;
GENFID(expnomodel);
WRPA(name, expnopeak, 1, disk, user);

//DATASET(name, expnopeak, 1, disk, user);
//FP;


if (imodelswitch==1){

	//  reverse phasing of 1D spectrum...
    
DATASET(name,expnomodel, 1, disk, user);
FT;
VIEWDATA;
//Proc_err(DEF_ERR_OPT,"phco: %f\nphc1: %f",fphc0,fphc1);
    STOREPAR("PHC0", 0.0-fphc0);
    STOREPAR("PHC1", 0.0-fphc1);
    STOREPAR("WDW", iWindow);
    FP;
    IFT;
    GENFID(expnomodel);
    FT;
    VIEWDATA;
FETCHPAR("PHC0",&fphc0);
FETCHPAR("PHC1",&fphc1);
//Proc_err(DEF_ERR_OPT,"phco: %f\nphc1: %f",fphc0,fphc1);   
    STOREPAR("PHC0", 0.0);
    STOREPAR("PHC1", 0.0);
FP;
VIEWDATA;
WRPA(name, expnopeak, 1, disk, user);
}



/*if ((fx1r=fopen(fnpeak,"rb")) == NULL)
{
    (void)sprintf(text,"Cannot read 1r file:\n%s ",fnpeak);
    STOPMSG(text);
}*/

DATASET(name,expnomodel, 1, disk, user);

STOREPARS("TD",4096);

(void)sprintf( fnmodel,"%s/data/%s/nmr/%s/%d/fid",disk,user,name,expno);

if ((fq1r=fopen(fnmodel,"rb")) == NULL)
{
    (void)sprintf(text,"Cannot read fid:\n%s ",fnmodel);
    STOPMSG(text);
}

i = fread(iBuffer,sizeof(int),iSI,fq1r);
fclose(fq1r);

	if (imodelswitch==1){
//leftshift the fid.
		//Proc_err(DEF_ERR_OPT,"This is in the leftshift portion.");
		fDelay = fD2/fDW;
		iD = (int) (fDelay/2.0);
		for (i=0; i < ((iSI)-2*iD); i=i+2) { 
		iBuffer[i]= iBuffer[i+2*iD]; 
		iBuffer[i+1]= iBuffer[i+2*iD+1];}
		for (i=((iSI)-2*iD); i < (iSI); i++) { iBuffer[i]= 0; }

fp1r=fopen(fnmodel,"wb");
fwrite(iBuffer,sizeof(int),iSI,fp1r);
fclose(fp1r);

//Apply window function.
    EFP;
    IFT;
    GENFID(expnomodel);
    FT;
		}
	if (imodelswitch==3){
//frequency shift the fid by 1J/2.
		GETINT("Left- (1) or the right-hand (2) peak of doublet?",ihalfswitch);
		foneJ/=2.0;
		if (ihalfswitch==1){
		foneJ*=-1.0;
		for (i=0; i < (iSI); i = i + 2) { 
		fCosWt=cos(i*foneJ*fDW*2*Pi);
		fSinWt=sin(i*foneJ*fDW*2*Pi);
		Number = iBuffer[i];
		iBuffer[i] =(Number*fCosWt-iBuffer[i+1]*fSinWt); 
		iBuffer[i+1] =(iBuffer[i+1]*fCosWt+Number*fSinWt); 
		}
		}
	if (ihalfswitch==2){
		for (i=0; i < (iSI); i = i + 2) { 
		fCosWt=cos(i*foneJ*fDW*2*Pi);
		fSinWt=sin(i*foneJ*fDW*2*Pi);
		Number = iBuffer[i];
		iBuffer[i] =(Number*fCosWt-iBuffer[i+1]*fSinWt); 
		iBuffer[i+1] =(iBuffer[i+1]*fCosWt+Number*fSinWt); 
		}
		}
		
fp1r=fopen(fnmodel,"wb");
fwrite(iBuffer,sizeof(int),iSI,fp1r);
fclose(fp1r);
}
DATASET(name,expnomodel, 1, disk, user);
WRPA(name, expnopeak, 1, disk, user);



if ((fq1r=fopen(fnmodelfid,"rb")) == NULL)
{
    (void)sprintf(text,"Cannot read fid:\n%s ",fnmodelfid);
    STOPMSG(text);
}
iTD=iSI;


i = fread(iBuffer,sizeof(int),iSI,fq1r);
fclose(fq1r);
if (iTD != i)   { STOPMSG("Read Error2:  SI != Number of Points Read"); }

// Calculate Chi squared for the parameters here.

if ((fr1r=fopen(fnslicefid,"rb")) == NULL)
{
    (void)sprintf(text,"Cannot read fid:\n%s ",fnslicefid);
    STOPMSG(text);
}


if ((fq1r=fopen(fnmodel,"rb")) == NULL)
{
    (void)sprintf(text,"Cannot read fid:\n%s ",fnmodel);
    STOPMSG(text);
}


iBuffer3=(int *) malloc((size_t)(iSI*sizeof(int)));
if (!iBuffer3) STOPMSG("Could not allocate enough memory (iBuffer3)");

dbox=(double *) malloc((size_t)(iSI*sizeof(double)));
if (!dbox) STOPMSG("Could not allocate enough memory (dbox)");


j = fread(iBuffer2,sizeof(int),iSI,fr1r);
fclose(fr1r);
if (i != j) {
    (void)sprintf( text, "Files of unequal size\n%s: %d bytes\n%s: %d bytes",
    fnmodelfid, model_filsiz, fnslicefid, slice_filsiz );
    STOPMSG( text );
}


j=0;

for (i=0;i<a;i++){
for (j=0;j<a;j++){
dChisq[i][j]=0.0;
}}


fJtestmin = 2.0;
fJtestmax = 12.0;
fAmax =  2.0;
fAmin = -2.0;

if (imodelswitch == 1 ) { 
fAmax =  1.0;
fAmin = -1.0;
}

for (p = 0; p <a; p++){
fA = (float)((fAmax-fAmin) * p) / a + fAmin;
for (q = 0; q < a; q++){
fJtest= (float)((fJtestmax-fJtestmin)  * q) / (float)a + fJtestmin;


for (i=0; i < (iSI); i = i + 2)
{
fSinpijt =  sin(i * fDW * fJtest * Pi);
iBuffer3[i]=iBuffer[i];
iBuffer3[i+1]=iBuffer[i+1];
iBuffer3[i]*=fA*fSinpijt;
iBuffer3[i+1]*=fA*fSinpijt;

dbox[i] = (double) (iBuffer3[i]-iBuffer2[i]);
dbox[i] *= dbox[i];
dbox[i+1] = (double) (iBuffer3[i]-iBuffer2[i]);
dbox[i+1] *= dbox[i+1];

dChisq[p][q] += dbox[i];
dChisq[p][q] += dbox[i+1];
}

DATASET(name, expnohmbc, 1, disk, user);

        //Proc_err(INFO_OPT,"J: %f\nA: %f",fJtest,fA);
(void)sprintf(text,"J: %f\nA: %f",fJtest,fA);
Show_status(text);
}
        //Proc_err(INFO_OPT,"J: %f\nA: %f",fJtest,fA);
}


dMax = 0.0;
for (p = 0; p < a; p++){
for (q = 0; q < a; q++){
if (dChisq[p][q] > dMax) {dMax = dChisq[p][q];}
}}
dMin = dMax;

for (p = 0; p < a; p++){
for (q = 0; q < a; q++){
if (dChisq[p][q] < dMin) {
dMin = dChisq[p][q];
pmin =p;
qmin=q;
}
}}
dMax = (dMax - dMin) /1000000.0;

for (p = 0; p < a; p++){
for (q = 0; q < a; q++){
i=a*a- a*p - q-1;
iBuffer3[i]=(int)((dChisq[p][q]-dMin)/dMax);
}}


fs1r=fopen(fnerr,"wb");
    fwrite(iBuffer3,sizeof(int),256,fs1r);
    fclose(fs1r);

// OK.  everything up to this point is just the setup.  From here down es serio.
//  Add things in line by line and see if it compiles.


//Get the buffers set up for itemplate, imodel, iclay, idydA, idydJ.


//iclay

    if ((fp1r=fopen(fnmodelfid,"rb")) == NULL)
    {
        (void)sprintf(text,"Cannot read clay 1r file:\n%s ",fnmodelfid);
        STOPMSG(text);
    }


    iclay=(int *) malloc((size_t)(iSI*sizeof(int)));
    if (!iclay) STOPMSG("Could not allocate enough memory (iclay)");

    i = fread(iclay,sizeof(int),iSI,fp1r);
    fclose(fp1r);

//itemplate
    if ((fr1r=fopen(fnslicefid,"rb")) == NULL)
{
    (void)sprintf(text,"Cannot read fid:\n%s ",fnslicefid);
    STOPMSG(text);
}

    itemplate=(int *) malloc((size_t)(iSI*sizeof(int)));
    if (!itemplate) STOPMSG("Could not allocate enough memory (itemplate)");

    i = fread(itemplate,sizeof(int),iSI,fr1r);
    fclose(fr1r);

//imodel


    imodel=(int *) malloc((size_t)(iSI*sizeof(int)));
    if (!imodel) STOPMSG("Could not allocate enough memory (imodel)");

//idydA


    idydA=(float *) malloc((size_t)(iSI*sizeof(int)));
    if (!idydA) STOPMSG("Could not allocate enough memory (idydA)");
//idydJ


    idydJ=(float *) malloc((size_t)(iSI*sizeof(int)));
    if (!idydJ) STOPMSG("Could not allocate enough memory (idydJ)");

//idydW


    idydW=(float *) malloc((size_t)(iSI*sizeof(int)));
    if (!idydW) STOPMSG("Could not allocate enough memory (idydW)");



fJtest= (float)((fJtestmax-fJtestmin)  * qmin) / (float)a + fJtestmin;
fA = (float)((fAmax-fAmin) * pmin) / a + fAmin;

GETFLOAT("Do you want to start with Jtrial as... ? ", fJtest);
GETFLOAT("Do you want to start with Atrial as... ? ", fA);


fAbest = fA;
fJbest = fJtest;
fW=0.0;

fChisq=0.0;
flamda=0.001;
for (i=0; i < 2; i++)
{
for (j=0; j < 2; j++)
{
alpha[i+1][j+1]=0.0;
}
}

beta[1] =0.0;
beta[2] =0.0;
beta[3] =0.0;

betaold[1]=beta[1];
betaold[2]=beta[2];
betaold[3]=beta[3];

for (i=0; i < (iSI); i = i + 2)
{
fSinpijt = sin(i * fDW * fJtest * Pi);
fCospijt = cos(i * fDW * fJtest * Pi);
fSinWt = sin((i * fDW) * fW *2*Pi  );
fCosWt = cos((i * fDW) * fW *2*Pi );

imodel[i]=fA*fSinpijt*(iBuffer[i]*fCosWt-iBuffer[i+1]*fSinWt);
imodel[i+1]=fA*fSinpijt*(iBuffer[i+1]*fCosWt+iBuffer[i]*fSinWt); 

dy = imodel[i] - itemplate[i];
dz = imodel[i+1] - itemplate[i+1];

//I don't know how to set up a 2D matrix, so i will resort to dyda1[i] etc.
//dyda[1][i] = imodel[i]/fA;
//dyda[1][i+1] = imodel[i+1]/fA;

idydA[i] = (double)(imodel[i]/fA);
idydA[i+1] = (double)(imodel[i+1]/fA);

idydJ[i] = (double)(iBuffer[i]*fCospijt*fA*Pi*i * fDW);
idydJ[i+1] = (double)(iBuffer[i+1]*fCospijt*fA*Pi*i * fDW);

idydW[i] = (double)(fA*fSinpijt*i*fDW*(-iBuffer[i]*fSinWt-iBuffer[i+1]*fCosWt));
idydW[i+1] = (double)(fA*fSinpijt*i*fDW*(-iBuffer[i+1]*fSinWt+iBuffer[i]*fCosWt));

fChisq+=dy*dy+dz*dz;

//alpha[1][1]+=idydA[i]*idydA[i];
//alpha[1][2]+=idydA[i]*idydJ[i];
//alpha[2][2]+=idydJ[i]*idydJ[i];
beta[1] += (double)(dy*idydA[i]);
beta[1] += (double)(dz*idydA[i+1]);
beta[2] += (double)(dy*idydJ[i]);
beta[2] += (double)(dz*idydJ[i+1]);
beta[3] += (double)(dy*idydW[i]);
beta[3] += (double)(dz*idydW[i+1]);
}
//Proc_err(DEF_ERR_OPT,"beta1: %f\nbet2: %f",beta[1],beta[2]);

foChisq=fChisq;


//

beta[1] /= pow((beta[1]*beta[1]+beta[2]*beta[2]),.5);
beta[2] /= pow((beta[1]*beta[1]+beta[2]*beta[2]),.5);
beta[3] /= pow((beta[1]*beta[1]+beta[2]*beta[2]+beta[3]*beta[3]),.5);
//Proc_err(DEF_ERR_OPT,"beta1: %f\nbet2: %f",beta[1],beta[2]);

fJtest-=beta[2];
fA-=beta[1];
fW-=beta[3];
//Proc_err(INFO_OPT,"gamma: %f",gamma);
betaold[1]=beta[1];
betaold[2]=beta[2];
betaold[3]=beta[3];
gamma=1.0;
counter=0;
while (gamma>0.00001&&counter<500)
{
counter++;
//Proc_err(DEF_ERR_OPT,"gamma: %f",gamma);

Proc_err(INFO_OPT,"J: %f",fJtest);
fChisq=0.0;
beta[1] = 0.0;
beta[2] = 0.0;
beta[3] = 0.0;

for (i=0; i < (iSI); i = i + 2)
{
    fSinpijt = sin(i * fDW * fJtest * Pi);
    fCospijt = cos(i * fDW * fJtest * Pi);

fSinWt = sin(i * fDW * fW *2*Pi);
fCosWt = cos(i * fDW * fW *2*Pi);

imodel[i]=fA*fSinpijt*(iBuffer[i]*fCosWt-iBuffer[i+1]*fSinWt);
imodel[i+1]=fA*fSinpijt*(iBuffer[i+1]*fCosWt+iBuffer[i]*fSinWt); 

    dy = imodel[i] - itemplate[i];

//I don't know how to set up a 2D matrix, so i will resort to dyda1[i] etc.
//dyda[1][i] = imodel[i]/fA;
//dyda[1][i+1] = imodel[i+1]/fA;

    idydA[i] = (double)(imodel[i]/fA);
    idydA[i+1] = (double)(imodel[i+1]/fA);

idydJ[i] = (double)(fCospijt*fA*Pi*i*fDW*(iBuffer[i]*fCosWt-iBuffer[i+1]*fSinWt ));	
idydJ[i+1] = (double)(fCospijt*fA*Pi*i*fDW*(iBuffer[i+1]*fCosWt+iBuffer[i]*fSinWt ));  


idydW[i] = (double)(fA*fSinpijt*i*fDW*(-iBuffer[i]*fSinWt-iBuffer[i+1]*fCosWt));
idydW[i+1] = (double)(fA*fSinpijt*i*fDW*(-iBuffer[i+1]*fSinWt+iBuffer[i]*fCosWt));


    fChisq+=dy*dy;

    //alpha[1][1]+=idydA[i]*idydA[i];
    //alpha[1][2]+=idydA[i]*idydJ[i];
    //alpha[2][2]+=idydJ[i]*idydJ[i];
beta[1] += (double)(dy*idydA[i]);
beta[1] += (double)(dz*idydA[i+1]);
beta[2] += (double)(dy*idydJ[i]);
beta[2] += (double)(dz*idydJ[i+1]);
beta[3] += (double)(dy*idydW[i]);
beta[3] += (double)(dz*idydW[i+1]);
}

fhorse=(beta[1]*beta[1]+beta[2]*beta[2]+beta[3]*beta[3]);
beta[1] /= pow(fhorse,.5);
beta[2] /= pow(fhorse,.5);
beta[3] /= pow(fhorse,.5);


//Proc_err(DEF_ERR_OPT,"beta1: %f\nbeta2: %f",beta[1],beta[2]);
fgoat=(fChisq/foChisq);
//Proc_err(DEF_ERR_OPT,"oChisq: %f\nChisq: %f\n%f",fChisq,foChisq,fgoat);

if (fChisq <= foChisq) {

fAbest=fA;
fA-=beta[1]*gamma;          //if chisq improved from last iteration, update bestpars and Chisq
fJbest=fJtest;
fJtest-=beta[2]*gamma;
fDChisq=foChisq-fChisq;
foChisq=fChisq;
fWbest=fW;
fW-=beta[3]*gamma;
//Proc_err(DEF_ERR_OPT,"gamma: %f",gamma);
//Proc_err(DEF_ERR_OPT,"fJbest: %f\nfAbest: %f",fJbest,fAbest);
betaold[1]=beta[1];
betaold[2]=beta[2];
betaold[3]=beta[3];
}
else
{
gamma/=2.0;
fA=fAbest-betaold[1]*gamma;         //if chisq didnt improve from last iteration, reset fA and Jtest, then step them half as far.
fJtest=fJbest-betaold[2]*gamma;
fW=fWbest-betaold[3]*gamma;	
}
}
Proc_err(INFO_OPT,"fJbest: %f\nfAbest: %f",fJbest,fAbest);

//STOREPARS("TD",iSI);
//STOREPAR("PARMODE",0);
//STOREPARS("PARMODE",0);


//fA = (float)((fAmax-fAmin) * pmin) / a + fAmin;
//fJtest= (float)((fJtestmax-fJtestmin)  * qmin) / (float)a + fJtestmin;
//Proc_err(INFO_OPT,"Jbest: %f\nAbest: %f",fJtest,fA);

for (i=0; i < (iSI); i = i + 2)
{
fSinpijt =  sin(i * fDW * fJbest * Pi);
fSinWt = sin(i * fDW * fWbest *2*Pi);
fCosWt = cos(i * fDW * fWbest *2*Pi);

iBuffer3[i]=fAbest*fSinpijt*(iBuffer[i]*fCosWt-iBuffer[i+1]*fSinWt);
iBuffer3[i+1]=imodel[i+1]=fAbest*fSinpijt*(iBuffer[i+1]*fCosWt+iBuffer[i]*fSinWt); 
}
fq1r=fopen(fnmodelfid,"wb");
    fwrite(iBuffer3,sizeof(int),iTD,fq1r);
    fclose(fq1r);
//DATASET(name, expno1d, 1, disk, user);
//Proc_err(DEF_ERR_OPT,"This might be where the problem sets in");
//FP;
//FP;
DATASET(name, expnomodel, 1, disk, user);
STOREPARS("TD",iSI);
STOREPAR("PHC0",0.0);
FP;
(void)sprintf( fntitle,"%s/data/%s/nmr/%s/%d/pdata/1/title",disk,user,name,expno);
fq1r=fopen(fntitle,"w");
fprintf(fq1r,"Model spectrum : J = %f Hz, shift = %f Hz",fJbest,fWbest);
fclose(fq1r);
DATASET(name, expnoslice, 1, disk, user);
STOREPARS("TD",iSI);
STOREPAR("PHC0",0.0);
FP;

DATASET(name, expnoerr, 1, disk, user);
VIEWDATA;
(void)sprintf( fntitle,"%s/data/%s/nmr/%s/%d/pdata/1/title",disk,user,name,expno);
fq1r=fopen(fntitle,"w");
fprintf(fq1r,"Error Map");
fclose(fq1r);

//This extra bit is to write the number out.

DATASET(name, expnohmbc, 1, disk, user);
STOREPAR("CNST 1",fJbest);

DATASET(name, expnomodel, 1, disk, user);
    WRPA(name, expnostore, 1, disk, user);
DATASET(name, expnoslice, 1, disk, user);
    WRPA(name, expnostore+1, 1, disk, user);
DATASET(name, expnostore, 1, disk, user);
DATASET2(name, expnostore+1, 1, disk, user);

free(dbox);
free(iBuffer);
free(iBuffer2);
free(iBuffer3);
free(iclay);
free(itemplate);
free(imodel);
free(idydA);
free(idydJ);
QUIT;
